/*******************************************************************************
* Copyright (C) 2014 Maxim Integrated Products, Inc., All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Maxim Integrated
* Products, Inc. shall not be used except as stated in the Maxim Integrated
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
*******************************************************************************
*/
/*============================================================================
 * 
 * Author(s): Maxim Integrated Products
 * Contributors:
 * Date:          
 * Purpose:       
 * Description:
 * 
 *==========================================================================*/
#ifndef _EMV_SLOT_H_
#define _EMV_SLOT_H_

/** Global includes */
/** Other includes */
#include <mml_sc.h>
/** Local includes */
#include <libemv.h>

#define EMV_PROTOCOL_T0			0x00
#define EMV_PROTOCOL_T1			0x01
/* Bug correction #769 */
#define EMV_PROTOCOL_T14		0x0e
/*  */

#define EMV_CONV_UNKNOWN 0xff
#define EMV_CONV_DIRECT 0
#define EMV_CONV_INVERSE 1

#define TAILLE_HISTO_MAX 15

// Apdu commande : CLA/INS/P1/P2/Lc/[254 octets]/Le   Apdu reponse : [254 octets]/ME1/ME2
#define EMV_CONFIG_APDU_MAX_SIZE 260

#define CWT_OFFSET_ERROR             5 /* FIME accept CWT+4 reject to 6 */

/* ApplicateATRValue definitions */
#define	HAL_SCS_APPLY_NONE							0x00
#define	HAL_SCS_APPLY_FD							0x01
#define HAL_SCS_APPLY_OTHER_ATR_VALUES				0x02
#define HAL_SCS_APPLY_ALL							(HAL_SCS_APPLY_OTHER_ATR_VALUES + HAL_SCS_APPLY_FD)

typedef struct 
{
	/** \showinitializer Contains ATR Historical Bytes  (ISO 7816-3:2006 8.2.4)
	 */
	unsigned char hist_bytes[16] ;
	/** \showinitializer Number of Histerical bytes */
	unsigned char k ;
	/** \showinitializer Convention: Direct or Indirect */
	unsigned char conv ;
	/** \showinitializer Protocol T=0 or T=1   */
	unsigned char protocol ;
	/** \showinitializer Maximum Information Field Size for the Card */
	unsigned char ifsc ;
	/** \showinitializer Maximum Information Field Size for the Reader */
	unsigned char ifsd ;
	/** \showinitializer Block Waiting time Integer  */
	unsigned char bwi;
	/** \showinitializer Character Waiting time Integer   */
	unsigned char cwi;
	/** \showinitializer Extra Guard Time Integer     */
	unsigned char n ;
	/** \showinitializer Waiting time Integer */
	unsigned char wi ;
	/** \showinitializer Default f value */
	unsigned char fd;
	/** \showinitializer Indicated f value */
	unsigned char fi ;
	/** \showinitializer Default D value  */
	unsigned char di ;
	/** \showinitializer Indicated D value  */
	unsigned char p ;
	/** \showinitializer Indicate if the ATR is EMV compliant(1) or not (0) */
	unsigned char emv_flag ;
	/** \showinitializer Character Waiting Time */
	unsigned long int cwt ;
	/** \showinitializer Block Waiting Time  */
	unsigned long int bwt ;
	
} emv_atr_t __attribute__ ((aligned(4)));




typedef struct 
{
	/** \showinitializer Buffer Data  */
    unsigned char data[EMV_CONFIG_APDU_MAX_SIZE];
    /** \showinitializer Buffer Length  */
    unsigned int length;
     
} emv_buf_t __attribute__ ((aligned(4)));

typedef struct 
{
	/** \showinitializer APDU Data */
    unsigned char *data;
    /** \showinitializer APDU Length  */
    unsigned int *length;
    /** \showinitializer ???  */
    unsigned int alloc;
     
} emv_apdu_t __attribute__ ((aligned(4)));

#define emv_buffer_get(_buf_)					_buf_.data
#define emv_buffer_get_len(_buf_)				_buf_.length
#define emv_buffer_init(_buf_)					_buf_.length = EMV_CONFIG_APDU_MAX_SIZE
#define emv_buffer_get_alloc()					EMV_CONFIG_APDU_MAX_SIZE

#define emv_apdu_get(_apdu_)					_apdu_.data
#define emv_apdu_get_len(_apdu_)				*_apdu_.length
#define emv_apdu_len(_apdu_)					_apdu_.length
#define emv_apdu_get_alloc(_apdu_)				_apdu_.alloc
#define emv_apdu_init(_apdu_, _ptr_, _len_)     _apdu_.data = _ptr_;    \
                                                _apdu_.alloc_ = *_len_; \
                                                _apdu_.length = _len_;  \
                                                *_apdu_.length = 0

#define EMV_STATE_MODE_NEGOCIABLE				0x00
#define EMV_STATE_INITIALIZED					0x01
#define EMV_STATE_COLD_RESET					0x02
#define EMV_STATE_MODE_SPECIFIC					0x04
#define EMV_STATE_OPERATION_PENDING				0x10
#define EMV_STATE_TIMER_PENDING					0x20
#define EMV_STATE_IFSD_PENDING					0x40
#define EMV_STATE_PPS_PENDING					0x80
#define EMV_STATE_DO_WARM_RESET					0x100
typedef void (*__emv_p_handlers)(int event );
typedef struct 
{
	/** \showinitializer Block Waiting Time */
    unsigned int		bwt ;
    /** \showinitializer Character Waiting Time  */
    unsigned int		cwt ;
    /** \showinitializer Possible values are an OR combinaison :
         *  #EMV_MODE_MANAGE_PPS
         *  #EMV_MODE_T1_MANAGE_RESYNC
         */
    unsigned int		ucFacteurD ;
    /** \showinitializer Possible values are an OR combinaison :
         *  #EMV_MODE_MANAGE_PPS
         *  #EMV_MODE_T1_MANAGE_RESYNC
         */
    unsigned int		usFacteurF ;
    /** \showinitializer ??????   */
    unsigned int		timernum ;
    /** \showinitializer Possible values are an OR combinaison :
         *  #EMV_MODE_MANAGE_PPS
         *  #EMV_MODE_T1_MANAGE_RESYNC
         */
    unsigned int		cycles ;
    /** \showinitializer State of State Machine         */
    int					state ;
    /** \showinitializer Possible values are an OR combinaison :
         *  #EMV_MODE_MANAGE_PPS
         *  #EMV_MODE_T1_MANAGE_RESYNC
         */
    int					flags ;
    /** \showinitializer Possible values are an OR combinaison :
         *  #EMV_MODE_MANAGE_PPS
         *  #EMV_MODE_T1_MANAGE_RESYNC
         */
    int					mode ;
    /** \showinitializer Possible values are an OR combinaison :
         *  #EMV_MODE_MANAGE_PPS
         *  #EMV_MODE_T1_MANAGE_RESYNC
         */
    int					devnum ;
    /** \showinitializer Possible values are an OR combinaison :
         *  #EMV_MODE_MANAGE_PPS
         *  #EMV_MODE_T1_MANAGE_RESYNC
         */
    volatile int		error ;
    /** \showinitializer Possible values are an OR combinaison :
         *  #EMV_MODE_MANAGE_PPS
         *  #EMV_MODE_T1_MANAGE_RESYNC
         */
    volatile int		status ;
    /** \showinitializer Card APDU
         */
    emv_apdu_t		    c_apdu ;
    /** \showinitializer Reader APDU */
    emv_apdu_t		    r_apdu ;
    /** \showinitializer TX Buffer  */
    emv_buf_t			tx_buf ;
    /** \showinitializer RX Buffer   */
    emv_buf_t			rx_buf ;
    /** \showinitializer Interrupt user service routines */
    __emv_p_handlers handlers[EMV_EVENT_COUNT];
    /** \showinitializer ATR Information  */
    volatile emv_atr_t           atr_info ;
    /** \showinitializer Received Data Length */
    unsigned int        rx_length;
    /** \showinitializer Waiting Time  */
    unsigned int		n ;
    /** \showinitializer Maximum Information Field for the card  */
    unsigned char       ifsc ;
    /** \showinitializer Retries  */
    unsigned char       retries ;
    /** \showinitializer Status Byte 1  */
    unsigned char		sw1 ;
    /** \showinitializer Status Byte 2  */
    unsigned char		sw2 ;
    /** \showinitializer Protocol T=0 or T=1 */
    unsigned char		protocol ;
    /** \showinitializer Sequence Number */
    unsigned char		seq ;
    /** \showinitializer Applicable Values */
    volatile unsigned char       ApplicableValues;
    /** \showinitializer Received Frame */
    unsigned char       rx_frame[6];
    /** \showinitializer to Send Frame */
    unsigned char       tx_frame[4];

} emv_slot_t __attribute__((aligned(4)));


extern emv_slot_t * emv_handles;

/* Bug correction #1037 */
#define	EMV_FAKE_ADD_PATTERN				0xffffffff
/*  */

#define emv_get_slot()   ((emv_handles))
       
#define L1_ErrLrc			0x11  
#define L1_ErrSequence		0x13

/* Replace memset */
/* Note here, because it's just the simplest rewritting of C standard function,
 * and because this function is private to this module,no check on pointers is done */
inline static void emv_memset(unsigned char *ptr, unsigned char value, unsigned int length)
{
	register unsigned int	i;

	for( i = 0;i < length;i++ )
	{
		ptr[i] = value;
	}
	return;
}
/* Replace memcpy */
/* Note here, because it's just the simplest rewritting of C standard function,
 * and because this function is private to this module,no check on pointers is done */
inline static void emv_memcpy( unsigned char *dest, unsigned char *src, unsigned int length)
{
	register unsigned int	i;

	for( i = 0;i < length;i++ )
	{
		dest[i] = src[i];
	}
	return;
}


inline static void emv_call_handler( emv_slot_t *slot, int event )
{
    if ( slot->handlers[event] ) 
        slot->handlers[event](event);
}

/**
 * The function sends an APDU command and gets the APDU response in T0 protocol .
 *
 * @param[in,out]	slot	Valid pointer to the structure which contains the APDU command
 *
 * @return 0 if the operation is successful, non-null value otherwise
 * (see \link Error_Codes Error Codes \endlink for a list of all error codes).
 *
 */
int emv_t0_transmit( emv_slot_t *slot );

/**
 * The function sends an APDU command and gets the APDU response in T1 protocol .
 *
 * @param[in,out]	slot:	Valid pointer to the structure which contains the APDU command
 *
 * @return 0 if the operation is successful, non-null value otherwise
 * (see \link Error_Codes Error Codes \endlink for a list of all error codes).
 *
 */
int emv_t1_transmit( emv_slot_t *slot );



/**
 * The function analyzes the ATR and set the structure "emv_slot_t" which stores static protocol values associated
 * to each card coupler.
 *
 * @param[in]	slot	Answer To Reset length
 *
 * @param[out]	info		Valid pointer to a structure containing the decoded values (protocol, TA1...)
 *
 * @return 0 if the operation is successful, non-null value otherwise
 * (see \link Error_Codes Error Codes \endlink for a list of all error codes).
 *
 */
int emv_atr_parse( emv_slot_t *slot, emv_atr_t *info );

void emv_calculate_timing( emv_slot_t *slot, emv_atr_t* info );
unsigned char emv_set_FD_values( emv_slot_t *slot, emv_atr_t* info, unsigned char Applicate );

int emv_t1_check_block(emv_slot_t *slot);
int emv_t1_block(emv_slot_t *slot,
					unsigned char pcb,
					unsigned char *info,
					unsigned int length);

/*
/------------------------------------------------------------
/ Define specifiques protocole T1
/------------------------------------------------------------
*/
#define STATE_T1_DONE							255
#define STATE_T1_START							0
#define STATE_T1_RECEIVE_BLOCK					1
#define STATE_T1_SEND_I_BLOCK					2
#define STATE_T1_SEND_R_BLOCK					3
#define STATE_T1_SEND_RESYNC					4
#define STATE_T1_RECEIVE_RESYNC					5
#define STATE_T1_RECEIVE_ABORT					6
#define BIT_PARITE_OU_EDC						1
#define BIT_OTHER_ERROR							2
#define CONFIG_EMV_T1_MAX_RETRIES				2
#define T_IBLOC									0
#define T_RBLOC									1
#define T_SBLOC									2
#define T_OTHER									0xff
#define WAIT_REQUEST							3
#define BLOCK_MASK								(unsigned char)0xC0
#define IBLOCK									(unsigned char)0x00
#define RBLOCK									(unsigned char)0x80
#define SBLOCK									(unsigned char)0xC0
#define RESYNC_REQ								(unsigned char)0xC0
#define RESYNC_RSP								(unsigned char)0xE0
#define IFS_REQ									(unsigned char)0xC1
#define IFS_RSP									(unsigned char)0xE1
#define ABORT_REQ								(unsigned char)0xC2
#define ABORT_RSP								(unsigned char)0xE2
#define WTX_REQ									(unsigned char)0xC3
#define WTX_RSP									(unsigned char)0xE3

#endif  /* _EMV_SLOT_H_ */
